from re import compile
from logging import getLogger

from zope.interface import implements, alsoProvides
from zope.viewlet.interfaces import IViewlet

from AccessControl import getSecurityManager
from Acquisition import aq_base, aq_inner
from Products.CMFPlone.utils import safe_unicode
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.CMFCore.utils import getToolByName

from plone.memoize import ram

from plone.app.layout.viewlets.common import ViewletBase

from meercat.ui.plone import labeledFilterQueryFieldExpression
from meercat.ui.plone.content.interfaces import sortFields



log = getLogger('meercat.ui.plone.browser.viewlets.common')

def paging_viewlet_render_cachekey(fun, self):
    """
    Generates a key based on:

    * View URL
    * SOLR Query parameters
    
    """
    
    return u''.join((
        self.view.absolute_url,
        self.view.getQueryParameters() and unicode(self.view.getQueryParameters()) or u'no parameters'))

class SearchSummaryViewlet(ViewletBase):
    numFound = 0
    
    def update(self):
        super(SearchSummaryViewlet,self).update()
        if self.view.hasPaginator():
            self.numFound = self.view.getPaginator().count

class SortSelectViewlet(ViewletBase):
    
    @property
    def available(self):
        log.debug('%s.available()' % (str(self)))
        return aq_inner(self.context).allowSortSelection and \
               len(self.getSortFields()) > 0 
    
    def getSortFields(self):
        log.debug('%s.getSortFields()' % (str(self)))
        
        return map(lambda field: dict(field=field[0],
                                      title=field[1],
                                      url=self.view.getUrlWithParams(sort=field[0],replace=True)),
                   sortFields)
    
    @property
    def action_url(self):
        log.debug('%s.action_url()' % (str(self)))
        return self.view.getUrlWithParams(remove=['sort'])

class FilterListViewlet(ViewletBase):
    fields = labeledFilterQueryFieldExpression
    queries = compile(r'^(?P<query>\?)$')
    dates = compile(r'^(?P<date>\?\?)$')
    filters = []
    
    def update(self):
        self.filters = self.request.get('fq',[])
        if not isinstance(self.filters,list):
            if self.filters:
                self.filters = [self.filters]
            else:
                self.filters = []
        
        self.filters = frozenset(self.filters)
    
    def hasFilters(self):
        return len(self.filters) > 0
    
    def getRemoveUrl(self, filter):
        return self.view.getUrlWithParams(remove=[('fq',filter)])
    
    def getFilterTitle(self, filter):
        m = self.fields.match(filter)
        if m:
            return self.getFieldFilterTitle(**m.groupdict())
        
        m = self.queries.match(filter)
        if m:
            return self.getQueryFilterTitle(**m.groupdict())
        
        m = self.dates.match(filter)
        if m:
            return self.getDateFilterTitle(**m.groupdict())
        
        return filter
    
    def getFieldFilterTitle(self, field=None, value=None, label=None):
        if label:
            return u'%s: %s' % (label, value,)
        
        return u'%s: %s' % (field, value)
    
    def getQueryFilterTitle(self, query):
        return query
    
    def getDateFilterTitle(self, date):
        return date
    
    def getRemoveLinks(self):
        log.debug('%s.getRemoveLinks() self.filters = %s' % (str(self),
                                                             str(self.filters),))
        return map(lambda f: {'title': self.getFilterTitle(f),
                              'url': self.getRemoveUrl(f)},self.filters)

class PagingViewlet(ViewletBase):
    #@ram.cache(paging_viewlet_render_cachekey)
    def render(self):
        log.debug('%s.render()' % (str(self),))
        return super(PagingViewlet,self).render()
    
    @property
    def page(self):
        try:
            return self.view.getCurrentPage()
        except:
            return None
    
    @property
    def paginator(self):
        try:
            return self.view.getPaginator()
        except:
            return None
    
    def getPageUrl(self, page=1):
        return self.view.getUrlWithParams(page=page)
    
    def getLimitedPageRange(self,size=4):
        log.debug('%s.getLimitedPageRange(size=%s)' % (str(self),str(size),))
        if not self.page or not self.paginator:
            return []
        
        if self.page.number <= size + 2:
            min = 1
            max = size*2
        elif self.page.number + size + 1 >= self.paginator.num_pages:
            min = self.paginator.num_pages - 2 * size
            max = self.paginator.num_pages
        else:
            min = self.page.number - size
            max = self.page.number + size
        
        if min < 1:
            min = 1
        
        if max > self.paginator.num_pages:
            max = self.paginator.num_pages
        
        return range(min,max+1)
    
